package sfeir.ergosum;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;

import sfeir.ergosum.dao.DatabaseConnection;
import sfeir.ergosum.dao.DatabaseProvider;
import sfeir.ergosum.dao.RemoteProvider;
import sfeir.ergosum.menu.HiveMainMenuActivity;
import sfeir.ergosum.model.Contact;
import sfeir.ergosum.model.Group;
import sfeir.ergosum.model.LetterIndex;
import sfeir.ergosum.service.ImportService;
import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.Menu;
import android.view.Window;
import android.widget.Toast;

import com.sfeir.proto.hivelayout.HiveScrolledView;

public class HiveActivity extends Activity {

    public final static int MAX_DISPLAY = 20;
    public static final int REFRESH = 100;

    private static BitmapDrawable hiveWallPaper;
    public static String PREFS_NAME;

    public final static int DIALOG_ADD_GROUP = 12;
    public final static int DIALOG_RENAME_GROUP = 13;
    public final static int DIALOG_RENAME_CONTACT = 14;
    public final static int DIALOG_MOVE_CONTACT = 15;
    public final static int DIALOG_PROGRESS = 16;
    private ProgressDialog mProgressDialog;

    Looper l;

    int orientation = 0;

    private HiveScrolledView hsv;

    private Thread mThread;
    private final Handler mHandler = new Handler() {
        public void handleMessage(Message msg) {
            if (R.id.hive_reset == msg.what) {
                HiveActivity.this.onResume();
                return;
            }
            super.handleMessage(msg);
        };
    };

    final Runnable invalidContact = new Runnable() {
        public void run() {
            Toast.makeText(HiveActivity.this,
                    getString(R.string.contact_invalid), 10000).show();
        }
    };
    final Runnable validContact = new Runnable() {
        public void run() {
            // startActivity(HiveActivity.this, "", "");
            onResume();
        }
    };

    final Runnable setupHiveView = new Runnable() {
        public void run() {
            hsv.getHv().setupNewCells();
        }
    };

    final Runnable setupAllHiveView = new Runnable() {
        public void run() {
            hsv.getHv().setupAll();
            l.quit();
        }
    };
    private BroadcastReceiver mContactReceiver;

    public HiveScrolledView getHsv() {
        return this.hsv;
    }

    public void setHsv(HiveScrolledView hsv) {
        this.hsv = hsv;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        PREFS_NAME = getPackageName()+"_preferences";
        setWallPaper();

        // Debug.startMethodTracing("hive" + System.currentTimeMillis());
        requestWindowFeature(Window.FEATURE_NO_TITLE);

        final long[] group = getIntent().getLongArrayExtra("group");
        final Group fixGroup = (Group) getIntent().getSerializableExtra(
                "FixGroup");
        final LetterIndex letter = (LetterIndex) getIntent()
                .getSerializableExtra("letter");
        final int level = getIntent().getIntExtra("level", 0);
        final Boolean actionPhone = getIntent().getBooleanExtra("actionPhone",
                true);

        final DatabaseProvider dp = new DatabaseProvider(
                new DatabaseConnection(getApplicationContext()));

        orientation = getWindow().getWindowManager().getDefaultDisplay()
                .getOrientation();

        if (letter != null) {
            hsv = new HiveScrolledView(this);
            hsv.getHv().setStatusBelowTitle(letter.getLetter());

            Thread contactThread = new Thread() {

                public void run() {
                    Looper.prepare();

                    boolean actionPhone = true;

                    dp.open();
                    List<Contact> allContacts = new ArrayList<Contact>();
                    switch (letter.getType()) {
                    case LetterIndex.TYPE_ROOT:
                        Log
                                .w("ROOTIDs", letter.getId() + " "
                                        + letter.getId2());
                        allContacts.addAll(dp
                                .getAllContactsFromIndex(letter.getId(),
                                        DatabaseProvider.KEY_CONTACT_LETTERID));
                        allContacts.addAll(dp.getAllContactsFromIndex(letter
                                .getId2(),
                                DatabaseProvider.KEY_CONTACT_FNLETTERID));
                        break;

                    case LetterIndex.TYPE_PHONE:
                        Log.w("PHONEIDs", letter.getId() + " "
                                + letter.getId2());
                        allContacts.addAll(dp.getAllContactsFromIndex(letter
                                .getId(),
                                DatabaseProvider.KEY_CONTACT_PHONEINDEX));
                        allContacts.addAll(dp.getAllContactsFromIndex(letter
                                .getId2(),
                                DatabaseProvider.KEY_CONTACT_FNPHONEINDEX));
                        break;

                    case LetterIndex.TYPE_SMS:
                        Log.w("SMSIDs", letter.getId() + " " + letter.getId2());
                        allContacts.addAll(dp.getAllContactsFromIndex(letter
                                .getId(),
                                DatabaseProvider.KEY_CONTACT_PHONEINDEX));
                        allContacts.addAll(dp.getAllContactsFromIndex(letter
                                .getId2(),
                                DatabaseProvider.KEY_CONTACT_FNPHONEINDEX));
                        hsv.getHv().setActionPhone(false);
                        actionPhone = false;
                        break;

                    case LetterIndex.TYPE_MAIL:
                        Log
                                .w("MAILIDs", letter.getId() + " "
                                        + letter.getId2());
                        allContacts.addAll(dp.getAllContactsFromIndex(letter
                                .getId(),
                                DatabaseProvider.KEY_CONTACT_MAILINDEX));
                        allContacts.addAll(dp.getAllContactsFromIndex(letter
                                .getId2(),
                                DatabaseProvider.KEY_CONTACT_FNMAILINDEX));
                        break;

                    default:
                        break;
                    }

                    dp.close();

                    if (allContacts.size() < MAX_DISPLAY) {
                        DatabaseProvider.sortContacts(allContacts);
                        for (Contact c : allContacts) {
                            hsv.getHv().addContactCell(c);
                            mHandler.post(setupHiveView);
                        }
                    }

                    if (allContacts.size() > 1)
                        for (Group g : getFilters(allContacts, level, letter
                                .getLetter())) {
                            g.setName(letter.getLetter() + g);
                            hsv.getHv().addDynaGroupCell(g, level, actionPhone);
                        }

                    do {

                    } while (!hsv.getHv().isConstantsOk());
                    l = Looper.myLooper();
                    mHandler.post(setupAllHiveView);
                    Looper.loop();

                }
            };
            contactThread.start();

            setContentView(hsv);

        } else if (group != null || fixGroup != null) {

            hsv = new HiveScrolledView(this);
            final String title = getIntent().getStringExtra("title");
            hsv.getHv().setStatusBelowTitle(title);

            if (fixGroup != null
                    && (fixGroup.getId() == -2 || fixGroup.getId() == -3 || fixGroup
                            .getId() == -4)) {
                hsv.getHv().setMinCellSize(40);

                Thread contactThread = new Thread() {

                    public void run() {
                        Looper.prepare();

                        boolean actionPhone = true;
                        List<LetterIndex> indexes;
                        dp.open();
                        if (fixGroup.getId() == -2) {
                            indexes = DatabaseProvider
                                    .indexFuuuuusion(
                                            dp
                                                    .getAllIndexes(DatabaseProvider.DATABASE_TABLE_PHONEINDEX),
                                            dp
                                                    .getAllIndexes(DatabaseProvider.DATABASE_TABLE_FNPHONEINDEX));
                        }

                        else if (fixGroup.getId() == -4) {
                            indexes = DatabaseProvider
                                    .indexFuuuuusion(
                                            dp
                                                    .getAllIndexes(DatabaseProvider.DATABASE_TABLE_PHONEINDEX),
                                            dp
                                                    .getAllIndexes(DatabaseProvider.DATABASE_TABLE_FNPHONEINDEX));
                            actionPhone = false;
                        } else
                            indexes = DatabaseProvider
                                    .indexFuuuuusion(
                                            dp
                                                    .getAllIndexes(DatabaseProvider.DATABASE_TABLE_MAILINDEX),
                                            dp
                                                    .getAllIndexes(DatabaseProvider.DATABASE_TABLE_FNMAILINDEX));
                        dp.close();

                        int max = 0;
                        for (LetterIndex li : indexes) {
                            if (li.getOccu() > max)
                                max = li.getOccu();
                        }

                        for (LetterIndex li : indexes) {
                            if (!actionPhone)
                                li.setType(LetterIndex.TYPE_SMS);
                            hsv.getHv().addLetterCell(li, max);
                        }
                        l = Looper.myLooper();
                        mHandler.post(setupAllHiveView);
                        Looper.loop();
                    }
                };
                contactThread.start();
            } else {
                Thread contactThread = new Thread() {

                    public void run() {
                        Looper.prepare();

                        List<Contact> allContacts;
                        dp.open();
                        if (group != null) {
                            allContacts = dp.getAllContactsFromTable(group);
                        } else {
                            allContacts = dp.getAllContactsFromGroup(fixGroup
                                    .getId());

                        }
                        dp.close();

                        if (allContacts.size() < MAX_DISPLAY) {
                            for (Contact c : allContacts) {
                                if (!actionPhone)
                                    hsv.getHv().setActionPhone(false);
                                hsv.getHv().addContactCell(c);
                                mHandler.post(setupHiveView);
                            }
                        }

                        if (allContacts.size() > 1)
                            for (Group g : getFilters(allContacts, level, title)) {
                                if (level > 0)
                                    g.setName(title + g.getName());
                                hsv.getHv().addDynaGroupCell(g, level,
                                        actionPhone);
                            }

                        l = Looper.myLooper();
                        mHandler.post(setupAllHiveView);
                        Looper.loop();
                    }
                };
                contactThread.start();

            }

            setContentView(hsv);
            // Debug.stopMethodTracing();

        }
    }

    private void setWallPaper() {
        // TODO check if we need to recycle wallDrawable
        int height = getWindow().getWindowManager().getDefaultDisplay()
                .getHeight();
        int width = getWindow().getWindowManager().getDefaultDisplay()
                .getWidth();
        BitmapDrawable wallDrawable = (BitmapDrawable) getWallpaper();
        Bitmap bitmapOrg = wallDrawable.getBitmap();
        Bitmap resizedBitmap = Bitmap.createBitmap(bitmapOrg,
                (640 - width) / 2, 0, width, height);
        BitmapDrawable hsvDrawable = new BitmapDrawable(resizedBitmap);
        // bitmapOrg.recycle();
        // resizedBitmap.recycle();
        hiveWallPaper = hsvDrawable;

    }

    /**
     * @return null is now wallPaperAvailable or a BitmapDrawable otherwise
     */
    public static BitmapDrawable getWallDrawable() {
        return hiveWallPaper;
    }

    @Override
    public void onResume() {
        super.onResume();
        mContactReceiver = new ContactReceiver();
        registerReceiver(mContactReceiver, new IntentFilter(
                ImportService.CONTACT_IMPORT_FINISHED));
        // Debug.startMethodTracing("hiver" + System.currentTimeMillis());

        // Gourmand en ressources
        final long[] group = getIntent().getLongArrayExtra("group");

        final Group fixGroup = (Group) getIntent().getSerializableExtra(
                "FixGroup");
        final LetterIndex letter = (LetterIndex) getIntent()
                .getSerializableExtra("letter");

        if (fixGroup == null && group == null && letter == null) {

            hsv = new HiveScrolledView(this);
            hsv.getHv().setMinCellSize(40);
            hsv.getHv().setStatusBelowTitle("Index");

            final DatabaseProvider dp = new DatabaseProvider(
                    new DatabaseConnection(getApplicationContext()));

            Thread contactThread = new Thread() {

                public void run() {
                    Looper.prepare();

                    dp.open();
                    List<LetterIndex> indexes = DatabaseProvider
                            .indexFuuuuusion(
                                    dp
                                            .getAllIndexes(DatabaseProvider.DATABASE_TABLE_LETTERINDEX),
                                    dp
                                            .getAllIndexes(DatabaseProvider.DATABASE_TABLE_FNLETTERINDEX));

                    List<Group> groups = dp.getAllGroups();
                    groups.remove(groups.size() - 1);
                    dp.close();

                    if (0 == indexes.size()) {
                        // Toast.makeText(HiveActivity.this, "No contacts",
                        // 3000).show();
                        // try {
                        // new
                        // ImportContacts(mHandler).importAllContacts(HiveActivity.this);
                        // } catch (InterruptedException e) {
                        // Toast.makeText(HiveActivity.this, "Cancelled",
                        // 3000).show();
                        // return;
                        // }
                        startService(new Intent(HiveActivity.this,
                                ImportService.class));
                    }

                    int max = 0;
                    for (LetterIndex li : indexes) {
                        if (li.getOccu() > max)
                            max = li.getOccu();
                    }

                    for (LetterIndex li : indexes) {
                        hsv.getHv().addLetterCell(li, max);
                    }

                    for (Group g : groups) {
                        // TODO : !!!!!!
                        dp.open();
                        hsv.getHv().addFixedGroupCell(g, true, 0);
                    }

                    Group gMail = new Group("Mail");
                    gMail.setId(-3);
                    hsv.getHv().addFixedGroupCell(gMail, false,
                            R.drawable.email);

                    Group gPhone = new Group("Phone");
                    gPhone.setId(-2);
                    hsv.getHv().addFixedGroupCell(gPhone, false,
                            R.drawable.phone_mobile);

                    Group gSms = new Group("Sms");
                    gSms.setId(-4);
                    hsv.getHv().addFixedGroupCell(gSms, false,
                            R.drawable.sms_icon);

                    dp.open();
                    hsv.getHv().setContactNumber(dp.getNumberOfContacts());
                    dp.close();

                    do {

                    } while (!hsv.getHv().isConstantsOk());
                    l = Looper.myLooper();
                    mHandler.post(setupAllHiveView);
                    Looper.loop();
                }
            };
            contactThread.start();
            // Debug.stopMethodTracing();

            setContentView(hsv);
        }
    }

    @Override
    protected void onPause() {
        unregisterReceiver(mContactReceiver);
        super.onPause();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // return MenuService.onCreateOptionsMenu(menu);
        startActivity(new Intent(this, HiveMainMenuActivity.class));
        return false;
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REFRESH) {
            if (resultCode == RESULT_OK) {
                startActivity(this, "", "");
            }
        }
    }

    @Override
    protected Dialog onCreateDialog(int id) {
        switch (id) {
        case DIALOG_PROGRESS:
            mProgressDialog = new ProgressDialog(this);
            mProgressDialog.setTitle(R.string.add_contact_wait_url);
            mProgressDialog.setIndeterminate(true);
            mProgressDialog.setButton2(getText(R.string.dialog_cancel),
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog,
                                int whichButton) {

                            mThread.stop();
                            mProgressDialog.dismiss();
                            /* User clicked No so do some stuff */
                        }
                    });
            return mProgressDialog;
        }
        return null;
    }

    @Override
    protected void onStart() {
        super.onStart();
        if (getIntent().hasExtra("code")) {
            Intent intent = getIntent();

            final String key = intent.getStringExtra("code");
            final String alias = intent.getStringExtra("alias");
            showDialog(DIALOG_PROGRESS);
            /* User clicked OK so do some stuff */
            mThread = new Thread() {
                public void run() {
                    RemoteProvider dao = new RemoteProvider(
                            new DatabaseConnection(getApplicationContext()));
                    if (dao.addContact(key, alias) == null) {
                        mProgressDialog.dismiss();
                        mHandler.post(invalidContact);
                    } else {
                        mProgressDialog.dismiss();
                        mHandler.post(validContact);
                    }
                }
            };
            mThread.start();

            intent.removeExtra("code");
            intent.removeExtra("alias");
        }
    }

    private List<Group> getFilters(List<Contact> contacts, int level,
            String title) {
        HashMap<String, Group> allFiltersMap = new HashMap<String, Group>();
        List<Group> allFilters = new ArrayList<Group>();

        for (Contact c : contacts) {
            String name = c.getPerson().getName().toUpperCase();
            String firstname = c.getPerson().getFirstname();

            if ((name.length() >= level + 1) && (name.startsWith(title))) {
                String s = name.substring(level, level + 1);
                if (allFiltersMap.containsKey(s)) {
                    allFiltersMap.get(s).addContact(c);
                } else {
                    Group g = new Group(s);
                    g.addContact(c);
                    allFiltersMap.put(s, g);
                }
            }
            if (firstname != null) {
                firstname = firstname.toUpperCase();
                if ((firstname.length() >= level + 1)
                        && firstname.startsWith(title)) {
                    String s = firstname.substring(level, level + 1);
                    if (allFiltersMap.containsKey(s)) {
                        Group g = allFiltersMap.get(s);
                        if (!g.getContacts().contains(c))
                            g.addContact(c);
                    } else {
                        Group g = new Group(s);
                        g.addContact(c);
                        allFiltersMap.put(s, g);
                    }
                }
            }
        }

        for (Group g : allFiltersMap.values()) {
            allFilters.add(g);
        }

        Collections.sort(allFilters, new Comparator<Group>() {
            @Override
            public int compare(Group object1, Group object2) {
                return -object1.getName().toUpperCase().compareTo(
                        object2.getName().toUpperCase());
            }
        });
        return allFilters;
    }

    public static void startActivity(Context context, String code, String alias) {
        Intent i = new Intent(context, HiveActivity.class);
        if (code.trim().length() != 0) {
            i.putExtra("code", code);
            i.putExtra("alias", alias);
        }
        i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        context.startActivity(i);
    }

    private class ContactReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            // Toast.makeText(HiveActivity.this, "contact received : " +
            // intent.getStringExtra("url"), 1000).show();
            onResume();
        }
    }
}
